/**
 * @file    user_iir.c
 * @brief   IIR数字低通滤波器c语言实现
 * @author  王晓荣
 * @version v0.0.0
 * @data    2014-04-30
 * 
 * @par     Version    Date        Duthor        Description
 *          v0.0.0     2014-04-30  王晓荣        首次编写
 *
 * @par     技术指标
 *          采样频率    400 Hz
 *          通带边缘    35  Hz
 *          通带波纹    1   dB
 *          阻带边缘    44  Hz
 *          阻带衰减    15  dB
 */

#include "user_iir.h"
#include "stdint.h"
#include "ad.h"

#define ORDER_NUM    10    /**< 滤波器阶数 */

/** 滤波器系数表 */
static const SAMPLE_TYPE b[ ORDER_NUM + 1 ] =
{
	9.69510497786374e-07,
	9.69510497786374e-06,
	4.36279724003869e-05,
	0.000116341259734365,
	0.000203597204535139,
	0.000244316645442166,
	0.000203597204535139,
	0.000116341259734365,
	4.36279724003869e-05,
	9.69510497786374e-06,
	9.69510497786374e-07
};

static const SAMPLE_TYPE a[ ORDER_NUM + 1 ] =
{
	1,-6.23722088349676,
	17.9943698593746,
	-31.4781840099423,
	36.8598294683455,
	-30.1169108115777,
	17.3566051018367,
	-6.95608538906778,
	1.85306922136670,
	-0.295986048441550,
	0.0215062703523466
};

/** 差分方程数据缓存区 */
static SAMPLE_TYPE xBuf[ ORDER_NUM + 1 ];
static SAMPLE_TYPE yBuf[ ORDER_NUM + 1 ];

void iir_init( void )
{
    int i;
    SAMPLE_TYPE sum;

    sum = ( SAMPLE_TYPE )ad_get_value(  );
    for( i = 0; i <= ORDER_NUM; i++ )
    {
        yBuf[ i ] = xBuf[ i ] = sum;
    }
}

SAMPLE_TYPE iir_exe( SAMPLE_TYPE x )
{
	int i;

	/** 运算之前Buf向前移动一个位置，以更新之前Buf的数据 */
	for( i = ORDER_NUM; i > 0; i-- )
	{
		yBuf[ i ] = yBuf[ i - 1 ];
		xBuf[ i ] = xBuf[ i - 1 ];
	}

	/** 更新数据表 */
	xBuf[ 0 ] = x;
	yBuf[ 0 ] = 0;

	/** 滤波变换 */
	for( i = 1; i <= ORDER_NUM; i++ )
	{
		yBuf[ 0 ] = yBuf[ 0 ] + b[ i ] * xBuf[ i ];
		yBuf[ 0 ] = yBuf[ 0 ] - a[ i ] * yBuf[ i ];
	}
	yBuf[ 0 ] =  yBuf[ 0 ] + b[ 0 ] * xBuf[ 0 ];

	/** 返回滤波值 */
	return yBuf[ 0 ];
}
